package org.theSeed.dataSource.pojo.prop;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.DruidPasswordCallback;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.theSeed.base.exp.ServiceExp;
import org.theSeed.base.utils.DeepCopyUtil;
import org.theSeed.dataSource.contract.DataSourceProp;
import org.theSeed.dataSource.pojo.dto.RelDbConnectInfo;

import javax.sql.DataSource;

/**
 * 德鲁伊数据源配置
 */
@Getter
@Setter
public class DruidProp implements DataSourceProp {
    /**
     * 连接池名称
     */
    private String poolName = "seedDruidPool";
    // 连接池优化配置
    /**
     * 初始化连接数
     * 5
     */
    private Integer initialSize = 5;
    /**
     * 最小空闲连接数
     * 5
     */
    private Integer minIdle = 5;
    /**
     * 最大连接数
     * 20
     */
    private Integer maxActive = 20;
    /**
     * 获取连接等待超时时间(毫秒)
     * 60000
     */
    private Integer maxWait = 60000;
    /**
     * 检查间隔
     * 60000
     */
    private Integer timeBetweenEvictionRunsMillis = 60000;
    /**
     * 最小生存时间
     * 300000
     */
    private Integer minEvictableIdleTimeMillis = 300000;
    /**
     * 验证查询
     * SELECT 1
     */
    private String validationQuery;
    /**
     * 空闲时检查
     * true
     */
    private Boolean testWhileIdle = true;
    /**
     * 获取连接时不检查
     * false
     */
    private Boolean testOnBorrow = false;
    /**
     * 归还连接时不检查
     * false
     */
    private Boolean testOnReturn = false;


    //高级配置
    /**
     * 启用监控统计功能
     * stat,wall,log4j
     */
    private String filters;

    /**
     * 连接属性
     * druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
     */
    private String ConnectionProperties;
    /**
     * 密码加密
     */
    private DruidPasswordCallback passwordCallback = new DruidPasswordCallback();

    //psCache配置
    private Boolean poolPreparedStatements = true;
    private Integer maxPoolPreparedStatementPerConnectionSize = 20;

    /**
     * 创建数据源
     * @param prop
     * @return
     */
    @SneakyThrows
    @Override
    public DataSource createDataSource(Object prop){
        if (prop instanceof RelDbConnectInfo){
            RelDbConnectInfo relDbConnectInfo = (RelDbConnectInfo)prop;
            DruidDataSource druidDataSource = new DruidDataSource();
            // 连接池优化配置
            druidDataSource.setInitialSize(getInitialSize());           // 初始化连接数
            druidDataSource.setMinIdle(getMinIdle());               // 最小空闲连接数
            druidDataSource.setMaxActive(getMaxActive());            // 最大连接数
            druidDataSource.setMaxWait(getMaxWait());           // 获取连接等待超时时间(毫秒)
            druidDataSource.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis()); // 检查间隔
            druidDataSource.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());   // 最小生存时间
            druidDataSource.setValidationQuery(getValidationQuery()); // 验证查询
            druidDataSource.setTestWhileIdle(getTestWhileIdle());      // 空闲时检查
            druidDataSource.setTestOnBorrow(getTestOnBorrow());      // 获取连接时不检查
            druidDataSource.setTestOnReturn(getTestOnReturn());      // 归还连接时不检查

            // 启用监控统计功能
            druidDataSource.setFilters(getFilters()); // 需要添加log4j依赖

            // 连接属性
            druidDataSource.setConnectionProperties(getConnectionProperties());

            // 密码加密
            druidDataSource.setPasswordCallback(getPasswordCallback());

            // PSCache配置
            druidDataSource.setPoolPreparedStatements(getPoolPreparedStatements());
            druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(getMaxPoolPreparedStatementPerConnectionSize());

            // 基本配置
            druidDataSource.setUrl(relDbConnectInfo.getJdbcUrl());
            druidDataSource.setUsername(relDbConnectInfo.getUsername());
            druidDataSource.setPassword(relDbConnectInfo.getPassword());
            druidDataSource.setDriverClassName(relDbConnectInfo.getDriverClassName());
            druidDataSource.init();
            return druidDataSource;
        }
        throw new ServiceExp("不支持配置初始化数据源");
    }
}
